# todo 这是用户的视图
from flask import request
from marshmallow import ValidationError
from sqlalchemy import desc, asc
from sqlalchemy.exc import SQLAlchemyError

from models import db, User
from utils import MD5, JWT, ThreadLocal
from common.ApiResponse import ApiResponse
from common.BaseResponse import BaseResponse
from common.ErrorCode import ErrorCode
from .validate import RegisterSchema, UpdateUserSchema, UpdatePsdSchema, UserAddSchema, UserUpdateSchema, ListUserSchema
from my_decorator.AuthCheck import auth_check
from constant.UserConstant import ADMIN_ROLE
from constant import CommonConstant

# 初始化校验器
register_schema = RegisterSchema()
update_schema = UpdateUserSchema()
update_psd_schema = UpdatePsdSchema()
user_add_schema = UserAddSchema()
user_update_schema = UserUpdateSchema()
list_schema = ListUserSchema()


# todo 注册视图
def register():
    try:
        # 验证请求参数
        errors = register_schema.load(request.form)
    except ValidationError as err:
        # 参数校验失败，返回错误信息
        error_response = BaseResponse.from_error_code(ErrorCode.PARAMS_ERROR)
        first_key, first_value = next(iter(err.messages.items()))
        return ApiResponse.error(message=error_response.message, code=error_response.code, data=first_value[0])

    username = request.form.get('username')
    password = request.form.get('password')
    # 检查用户是否已存在
    user = User.query_active().filter(User.username == username).first()
    if user:  # todo 统计结果返回封装
        error_response = BaseResponse.from_error_code(ErrorCode.PARAMS_ERROR)
        return ApiResponse.error(code=error_response.code, message=error_response.message,
                                 data=f"{username} 已经存在")
    print(f"username:{username}, password:{password}")
    # 对密码进行MD5加密
    password = MD5.Md5Util.get_md5_string(password)
    user = User(username=username, password=password)
    db.session.add(user)
    # 提交事务
    db.session.commit()
    return ApiResponse.success()


# todo 登录视图
def login():
    print(request.form)
    try:
        # 验证请求参数
        errors = register_schema.load(request.form)
    except ValidationError as err:
        error_response = BaseResponse.from_error_code(ErrorCode.PARAMS_ERROR)
        first_key, first_value = next(iter(err.messages.items()))
        return ApiResponse.error(message=error_response.message, code=error_response.code, data=first_value[0])

    username = request.form.get('username')
    password = request.form.get('password')
    password = MD5.Md5Util.get_md5_string(password)
    # 查询用户
    user = User.query_active().filter(User.username == username).first()
    if not user:
        error_response = BaseResponse.from_error_code(ErrorCode.PARAMS_ERROR)
        return ApiResponse.error(code=error_response.code, message=error_response.message, data="用户不存在")
    if password == user.password:
        # 生成JWT令牌
        user_map = {"id": user.id, "username": user.username,"user_role": user.user_role}
        token = JWT.JWTUtil.gen_token(user_map)
        return ApiResponse.success(data=token)
    error_response = BaseResponse.from_error_code(ErrorCode.PARAMS_ERROR)
    return ApiResponse.error(code=error_response.code, message=error_response.message, data="密码错误")


# todo 用户信息视图
def userInfo():
    # 获取当前用户信息
    user_map = ThreadLocal.ThreadLocalUtil.get()
    user_name = user_map.get("username")
    user = User.query_active().filter(User.username == user_name).first()
    if (not user):
        error_response = BaseResponse.from_error_code(ErrorCode.NOT_FOUND_ERROR)
        return ApiResponse.error(code=error_response.code, message=error_response.message, data="用户不存在")
    # 返回用户信息
    data = {
        "id": user.id,
        "username": user.username,
        "nickname": user.nickname,
        "email": user.email,
        "userPic": user.user_pic,
        "createTime": user.create_time.strftime("%Y-%m-%d %H:%M:%S"),
        "updateTime": user.update_time.strftime("%Y-%m-%d %H:%M:%S"),
        "user_role": user.user_role,
    }
    return ApiResponse.success(data=data)


# todo 用户更新信息视图
def update():
    # todo 前端记得加上一个用户简介的部分
    try:
        # 验证请求参数
        errors = update_schema.load(request.json)
    except ValidationError as err:
        error_response = BaseResponse.from_error_code(ErrorCode.PARAMS_ERROR)
        first_key, first_value = next(iter(err.messages.items()))
        return ApiResponse.error(message=error_response.message, code=error_response.code, data=first_value[0])

    data = request.json
    user_map = ThreadLocal.ThreadLocalUtil.get()
    old_user = User.query_active().filter(User.username == user_map.get("username")).first()
    # 更新用户信息
    old_user.nickname = data["nickname"]
    old_user.email = data["email"]
    old_user.user_profile = data["user_profile"]
    db.session.commit()
    return ApiResponse.success(data="更新成功")


# todo 用户头像
def avatar():
    avatar_url = request.args.get("avatarUrl")
    user_map = ThreadLocal.ThreadLocalUtil.get()
    user = User.query_active().filter(User.username == user_map.get("username")).first()
    # 更新用户头像
    user.user_pic = avatar_url
    db.session.commit()
    return ApiResponse.success(data=avatar_url)


# todo 用户修改密码视图
def updatePwd():
    data = request.json
    try:
        # 验证请求参数
        errors = update_psd_schema.load(request.json)
    except ValidationError as err:
        error_response = BaseResponse.from_error_code(ErrorCode.PARAMS_ERROR)
        first_key, first_value = next(iter(err.messages.items()))
        return ApiResponse.error(message=error_response.message, code=error_response.code, data=first_value[0])

    old_pwd = data.get("old_pwd")
    new_pwd = data.get("new_pwd")
    re_pwd = data.get("re_pwd")
    # 密码校验
    if old_pwd == new_pwd:
        error_response = BaseResponse.from_error_code(ErrorCode.PARAMS_ERROR)
        return ApiResponse.error(code=error_response.code, message=error_response.message, data="新旧密码一样")
    if new_pwd != re_pwd:
        error_response = BaseResponse.from_error_code(ErrorCode.PARAMS_ERROR)
        return ApiResponse.error(code=error_response.code, message=error_response.message,
                                 data="新密码与确认密码不一致")
    user_map = ThreadLocal.ThreadLocalUtil.get()
    user = User.query_active().filter(User.username == user_map.get("username")).first()
    if user.password != MD5.Md5Util.get_md5_string(old_pwd):
        error_response = BaseResponse.from_error_code(ErrorCode.PARAMS_ERROR)
        return ApiResponse.error(code=error_response.code, message=error_response.message, data="原密码错误")

    # 更新密码
    user.password = MD5.Md5Util.get_md5_string(new_pwd)
    db.session.commit()
    return ApiResponse.success(data="更新密码成功！")


# todo 根据token获取当前用户
def getLoginUser():
    try:
        token = request.headers.get("Authorization")
        user_map = JWT.JWTUtil.parse_token(token)
        user_name = user_map.get("username")
        user = User.query_active().filter(User.username == user_name).first()
        if (not user):
            error_response = BaseResponse.from_error_code(ErrorCode.NOT_FOUND_ERROR)
            return ApiResponse.error(code=error_response.code, message=error_response.message, data="用户不存在")
        # 返回用户信息
        data = {
            "id": user.id,
            "username": user.username,
            "nickname": user.nickname,
            "email": user.email,
            "userPic": user.user_pic,
            "createTime": user.create_time.strftime("%Y-%m-%d %H:%M:%S"),
            "updateTime": user.update_time.strftime("%Y-%m-%d %H:%M:%S"),
            "user_role": user.user_role,
            "user_profile":user.user_profile
        }
        return ApiResponse.success(data=data)
    except Exception as e:
        error_response = BaseResponse.from_error_code(ErrorCode.NOT_LOGIN_ERROR)
        return ApiResponse.error(code=error_response.code, message=error_response.message, data="token失效")

# 添加用户，需要管理员权限
@auth_check(required_roles=[ADMIN_ROLE])
def addUser():
    data = request.json
    if not data:
        error_response = BaseResponse.from_error_code(ErrorCode.PARAMS_ERROR)
        return ApiResponse.error(message=error_response.message, code=error_response.code, data="添加数据不存在")
    try:
        # 验证请求参数
        error = user_add_schema.load(data)
    except ValidationError as err:
        error_response = BaseResponse.from_error_code(ErrorCode.PARAMS_ERROR)
        return ApiResponse.error(message=error_response.message, code=error_response.code, data=err.messages)
    username = data.get("username")
    nickname = data.get("nickname")
    user_pic = data.get("user_pic")
    user_role = data.get("user_role")
    # 默认密码 123456
    password = "123456"
    user = User.query_active().filter(User.username == username).first()
    if user:  # todo 统计结果返回封装
        error_response = BaseResponse.from_error_code(ErrorCode.PARAMS_ERROR)
        return ApiResponse.error(code=error_response.code, message=error_response.message,
                                 data=f"{username} 已经存在")
    print(f"username:{username}, password:{password}")
    # 对密码进行MD5加密
    password = MD5.Md5Util.get_md5_string(password)
    user = User(username=username, password=password, nickname=nickname, user_pic=user_pic, user_role=user_role)
    db.session.add(user)
    # 提交事务
    db.session.commit()
    return ApiResponse.success()


# 删除用户，需要管理员权限
@auth_check(required_roles=[ADMIN_ROLE])
def deleteUser():
    user_id = request.args.get("id")
    user_id = int(user_id)
    print(user_id)
    if  user_id <= 0:
        error_response = BaseResponse.from_error_code(ErrorCode.PARAMS_ERROR)
        return ApiResponse.error(message=error_response.message, code=error_response.code, data="删除id非法")
    try:
        # 删除用户
        user = User.query_active().filter(User.id == user_id).first()
        print(user.__repr__())
        # 逻辑删除
        if user.isDelete==0:
            user.isDelete=1
            db.session.commit()
            return ApiResponse.success(data=f"已成功将该编号为{id}的用户删除！")
        else:
            user.isDelete=0
            db.session.commit()
            return ApiResponse.success(data=f"已成功将该编号为{id}的用户恢复！")
    except SQLAlchemyError as e:
        error_response = BaseResponse.from_error_code(ErrorCode.PARAMS_ERROR)
        return ApiResponse.error(message=error_response.message, code=error_response.code, data=str(e))


# 更新用户信息，需要管理员权限
#{"nickname":["Field may not be null."],"user_pic":["Field may not be null."],"username":["Unknown field."],"password":["Unknown field."]}
@auth_check(required_roles=[ADMIN_ROLE])
def updateUser():
    if not request.json or not request.json.get("id"):
        error_response = BaseResponse.from_error_code(ErrorCode.PARAMS_ERROR)
        return ApiResponse.error(message=error_response.message, code=error_response.code, data="更新id非法")
    id = request.json.get("id")

    try:
        # 验证请求参数
        error = user_update_schema.load(request.json)
    except ValidationError as err:
        error_response = BaseResponse.from_error_code(ErrorCode.PARAMS_ERROR)
        return ApiResponse.error(message=error_response.message, code=error_response.code, data=err.messages)

    nickname = request.json.get("nickname")
    user_pic = request.json.get("user_pic")
    username = request.json.get("username")
    user_role = request.json.get("user_role")
    try:
        # 更新用户信息
        User.query_active().filter(User.id == id).update(
            {"nickname": nickname,
             "user_pic": user_pic,
             "username": username,
             "user_role": user_role,
             }
        )
        db.session.commit()
        return ApiResponse.success()
    except SQLAlchemyError as e:
        error_response = BaseResponse.from_error_code(ErrorCode.PARAMS_ERROR)
        return ApiResponse.error(message=error_response.message, code=error_response.code, data=str(e))


# 获取任意用户信息，需要管理员权限
@auth_check(required_roles=[ADMIN_ROLE])
def getUserById():
    id = request.args.get("id")
    id = int(id)
    print(id)
    if id <= 0:
        error_response = BaseResponse.from_error_code(ErrorCode.PARAMS_ERROR)
        return ApiResponse.error(message=error_response.message, code=error_response.code, data="查询id非法")
    user = User.query_active().filter(User.id == id).first()
    if not user:
        error_response = BaseResponse.from_error_code(ErrorCode.NOT_FOUND_ERROR)
        return ApiResponse.error(message=error_response.message, code=error_response.code, data="用户不存在")
    return ApiResponse.success(data=user.to_dict())


# 分页获取用户完整信息列表，需要管理员权限
@auth_check(required_roles=[ADMIN_ROLE])
def listUserByPage():
    data = request.json
    for key in ["sortField", "sortOrder"]:
        if data.get(key) is None:
            schema = ListUserSchema()
            data[key] = schema.fields[key].default
    try:
        error = list_schema.load(data)
    except ValidationError as err:
        error_response = BaseResponse.from_error_code(ErrorCode.PARAMS_ERROR)
        return ApiResponse.error(message=error_response.message, code=error_response.code, data=err.messages)
    current = data.get("current")
    size = data.get("pageSize")
    print(type(current))
    nickname = data.get("nickname")
    user_profile = data.get("user_profile")
    user_role = data.get("user_role")
    sortField = data.get("sortField")
    sortOrder = data.get("sortOrder")
    try:
        query = User.query_active()
        if nickname:
            query = query.filter(User.nickname.like(f"%{nickname}%"))
        if user_profile:
            query = query.filter(User.user_profile.like(f"%{user_profile}%"))
        if user_role:
            query = query.filter(User.user_role == user_role)
        # todo 用户排序字段到底是哪些呢？
        column = getattr(User, sortField)
        if sortOrder == CommonConstant.SORT_ORDER_ASC:
            query = query.order_by(asc(column))
        else:
            query = query.order_by(desc(column))
        users = query.offset((current - 1) * size).limit(size).all()
        total = query.count()
        items = []
        for user in users:
            items.append(user.to_dict())
        data = {
            "total": total,
            "items": items,
        }
        print("data:",data)
        return ApiResponse.success(data=data)
    except SQLAlchemyError as e:
        print("rollback")
        db.session.rollback()
        error_response = BaseResponse.from_error_code(ErrorCode.PARAMS_ERROR)
        return ApiResponse.error(message=error_response.message, code=error_response.code, data=str(e))

#
def listUserVoPage():
    data = request.json
    try:
        error = list_schema.load(data)
    except ValidationError as err:
        error_response = BaseResponse.from_error_code(ErrorCode.PARAMS_ERROR)
        return ApiResponse.error(message=error_response.message, code=error_response.code, data=err.messages)
    current = data.get("current")
    size = data.get("size")
    current = int(current)
    size = int(size)
    nickname = data.get("nickname")
    user_profile = data.get("user_profile")
    user_role = data.get("user_role")
    sortField = data.get("sortField")
    sortOrder = data.get("sortOrder")
    try:
        query = User.query_active()
        if nickname:
            query = query.filter(User.nickname.like(f"%{nickname}%"))
        if user_profile:
            query = query.filter(User.user_profile.like(f"%{user_profile}%"))
        if user_role:
            query = query.filter(User.user_role == user_role)
        # todo 用户排序字段到底是哪些呢？
        column = getattr(User, sortField)
        if sortOrder == CommonConstant.SORT_ORDER_ASC:
            query = query.order_by(asc(column))
        else:
            query = query.order_by(desc(column))
        total = query.count()
        users = query.offset((current - 1) * size).limit(size).all()
        items = []
        for user in users:
            item = {
                "id": user.id,
                "nickname": user.nickname,
                "user_profile": user.user_profile,
                "user_role": user.user_role,
                "user_pic": user.user_pic,
                "createTime": user.createTime,
            }
            items.append(item)
        data = {
            "total": total,
            "items": items,
        }
        return ApiResponse.success(data=data)
    except SQLAlchemyError as e:
        db.session.rollback()
        error_response = BaseResponse.from_error_code(ErrorCode.PARAMS_ERROR)
        return ApiResponse.error(message=error_response.message, code=error_response.code, data=str(e))
